﻿#region

using System.Collections.Generic;
using System.Linq;
using System.Text;

#endregion

namespace Domain {
    public static class SupportGraphsBuilder {
        public static Graph<Edge> FindEdgedGraph(Graph<HyperEdge> hyperGraph) {
            var dictionary = new Dictionary<HyperEdge, Vertex>();
            var k = 0;
            hyperGraph.Edges.ForEach(e => dictionary.Add(e, new Vertex(k++, GetCorrespondingVertexName(e))));

            var edgedGraph = new Graph<Edge>(dictionary.Values.ToList());

            for (var i = 0; i < hyperGraph.Edges.Count - 1; i++) {
                for (var j = i + 1; j < hyperGraph.Edges.Count; j++) {
                    int weight;
                    var edge1 = hyperGraph.Edges[i];
                    var edge2 = hyperGraph.Edges[j];
                    if (AreAdjacent(edge1, edge2, out weight)) {
                        edgedGraph.AddEdge(new Edge(dictionary[edge1], dictionary[edge2], weight));
                    }
                }
            }
            return edgedGraph;
        }

        private static string GetCorrespondingVertexName(HyperEdge hyperEdge) {
            var builder = new StringBuilder();
            int i;
            for (i = 0; i < hyperEdge.Vertices.Count - 1; i++) {
                var v = hyperEdge.Vertices[i];
                builder.Append(v.Name).Append(@"'");
            }
            builder.Append(hyperEdge.Vertices[i]);
            return builder.ToString();
        }

        private static bool AreAdjacent(HyperEdge hyperEdge1, HyperEdge hyperEdge2, out int weight) {
            weight = hyperEdge1.Vertices.Count(vertex => hyperEdge2.Vertices.Contains(vertex));
            return weight > 0;
        }

        public static Graph<HyperEdge> FindVertexedGraph(Graph<HyperEdge> graph) {
            var max = graph.Vertices.Select(v => v.Id).Max(x => x)+1;
            var adjacencyMatrix = new bool[max,max];
            for (int i = 0; i < max; i++) {
                for (int j = 0; j < max; j++) {
                    adjacencyMatrix[i, j] = false;
                }
            }
            var vertices = new Vertex[graph.NumberVertices];
            graph.Vertices.CopyTo(vertices);
            var vertexedGraph = new Graph<HyperEdge>(vertices.ToList());
            var dictionary = new Dictionary<Vertex, Vertex>();
            for (int i = 0; i < graph.Vertices.Count; i++) {
                dictionary[graph.Vertices[i]] = vertexedGraph.Vertices[i];
            }

            foreach (var edge in graph.Edges) {
                for (int i = 0; i < edge.Vertices.Count-1; i++) {
                    for (int j = i+1; j < edge.Vertices.Count; j++) {
                        var vertex1 = dictionary[edge.Vertices[i]];
                        var vertex2 = dictionary[edge.Vertices[j]];
                        if (adjacencyMatrix[vertex1.Id, vertex2.Id]) continue;
                        adjacencyMatrix[vertex1.Id, vertex2.Id] = true;
                        vertexedGraph.AddEdge(new HyperEdge(vertex1, vertex2));
                    }
                }
            }
            return vertexedGraph;
        }
    }
}